package com.zero.ava.impl.kernel;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zero.ava.impl.kernel.KernelShutDownController;
import com.zero.ava.kernel.ComponentRegistry;
import com.zero.ava.management.KernelMXBean;

/**
 * 引擎的启动
 * 
 * @author mac
 * 
 */
public class Kernel {

	private static Logger logger = LoggerFactory.getLogger(Kernel.class);
	/**
	 * 内核组件管理器
	 */
	private final ComponentRegistry systemRegistry;

	private final KernelShutDownController shutDownController = new KernelShutdownContrllerImpl();

	protected Kernel(Properties appProperties) throws Exception {
		systemRegistry = new ComponentRegistryImpl();
	}

	private final class KernelShutdownContrllerImpl implements KernelShutDownController {

		@Override
		public void shutdownNode(Object caller) {
			logger.info("Close kernel");
		}

	}

	public class KernelManager implements KernelMXBean {

		@Override
		public void requestShutdown() {
			shutDownController.shutdownNode(this);
		}

	}

	public static void main(String[] args) throws Exception {
		// 确保没有过多的参数
		if (args.length > 1) {
			logger.info("Invalid number of arguments: halting");
			System.exit(1);
		}
		// 属性
		Properties appProperties;
		if (args.length == 1) {
			appProperties = findProperties(args[0]);
		} else {
			appProperties = findProperties(null);
		}
		Object object = appProperties.get(StandardProperties.APP_NAME);
		System.out.println(object);
		// 启动核心
		// new Kernel(appProperties);
	}

	/**
	 * 查找静态属性文件
	 * 
	 * @throws Exception
	 * @throws MalformedURLException
	 */
	private static Properties findProperties(String propLoc) throws MalformedURLException, Exception {
		// 加载扩展配置文件作为属性的默认设置（如果存在）
		Properties baseProperties = new Properties();
		String extPropFile = System.getProperty(BootProperties.EXTENSION_FILE_PROPERTY);
		if (extPropFile != null) {
			File extFile = new File(extPropFile);
			if (extFile.isFile() && extFile.canRead()) {
				baseProperties = loadProperties(extFile.toURI().toURL(), null);
			} else {
				logger.info("can't access file: " + extPropFile);
				throw new IllegalArgumentException("can't access file " + extPropFile);
			}
		}

		// 如果存在特定的应用程序的属性文件则加载
		URL propsIn = ClassLoader.getSystemResource(BootProperties.DEFAULT_APP_PROPERTIES);
		Properties appProperties = baseProperties;
		if (propsIn != null) {
			appProperties = loadProperties(propsIn, baseProperties);
		}

		// 加载传入的属性文件
		Properties fileProperties = appProperties;
		if (propLoc != null && !propLoc.equals("")) {
			File propFile = new File(propLoc);
			if (!propFile.isFile() || !propFile.canRead()) {
				logger.info("FScan't access file : " + propFile);
				throw new IllegalArgumentException("can't access file " + propFile);
			}
			fileProperties = loadProperties(propFile.toURI().toURL(), appProperties);
		}

		// 主目录存在配置文件的话，使用主目录的
		Properties homeProperties = fileProperties;
		File homeConfig = new File(System.getProperty("user.home") + File.separator + BootProperties.DEFAULT_HOME_CONFIG_FILE);
		if (homeConfig.isFile() && homeConfig.canRead()) {
			homeProperties = loadProperties(homeConfig.toURI().toURL(), fileProperties);
		} else if (homeConfig.isFile() && !homeConfig.canRead()) {
			logger.info("can't access file : " + homeConfig);
		}

		// 覆盖任何属性文件。优先使用主目录的属性配置文件
		Properties finalProperties = new Properties(homeProperties);
		finalProperties.putAll(System.getProperties());

		return finalProperties;
	}

	private static Properties loadProperties(URL resource, Properties backingProperties) throws Exception {
		InputStream in = null;
		try {
			Properties properties;
			if (backingProperties == null) {
				properties = new Properties();
			} else {
				properties = new Properties(backingProperties);
			}
			in = resource.openStream();
			properties.load(in);

			return properties;
		} catch (IOException ioe) {
			logger.info("Unable to load " + "from resource {0}: ", resource);
			throw ioe;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					logger.info("failed to close " + "resource {0}", resource);
				}
			}
		}
	}
}
